package org.redmagic.agent.location;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.redmagic.agent.MagicFileConfigurer;
import org.redmagic.exception.RedMagicConfigurationException;
import org.redmagic.location.Location;
import org.redmagic.location.LocationFactory;
import org.redmagic.utils.Conditions;
import org.redmagic.utils.Documents;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

public class DefaultLocationFactory implements LocationFactory {

	private static final String PARSER_SUFFIX = "Parser";
	
	private final Document document;
	private final Map<String, DomLocationParser> locationParsers;
	private final Object lock;
	
	private List<Location> locations = null;
	
	public DefaultLocationFactory(Map<String, DomLocationParser> locationParsers, MagicFileConfigurer configuration) {
	    Conditions.notNull(locationParsers, "locationParsers");
	    Conditions.notNull(configuration, "configuration");
		this.document = configuration.getResolvedContents();
		this.locationParsers = new HashMap<String, DomLocationParser>(locationParsers);
		this.lock = new Object();
	}
	
	@Override
	public List<Location> getLocations() {
	    synchronized(lock) {
	        if (locations == null) {
	            locations = parseLocations();
	        }
	        return locations;	        
	    }
	}

	private List<Location> parseLocations() {
		List<Location> parsedLocations = new ArrayList<Location>();
		Element rootElement = this.document.getDocumentElement();
		
		for (Element locationElement : Documents.getChildElements(rootElement)) {
		    Location location = parseLocation(locationElement);
			parsedLocations.add(location);
		}
		
		return parsedLocations;
	}

	private Location parseLocation(Element locationElement) {
		String locationParserName = locationElement.getNodeName() + PARSER_SUFFIX;
		DomLocationParser locationParser = locationParsers.get(locationParserName);
		if (locationParser != null) {
			return locationParser.parse(locationElement);
		}
		throw new RedMagicConfigurationException("No LocationParser found for type: " + locationParserName);
	}

}